package com.house365.app.analyse.http;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.SSLHandshakeException;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

/**
 * @author py
 * @date 2012-6-28
 * @comment
 */
public class AnalyseHttpAPI {
	private final DefaultHttpClient client;
	// private final HttpURLConnectionUtil standerHttp;
	public static final int CHANNLE_TYPE_STANDER = 1;
	public static final int CHANNLE_TYPE_COMMONS = 2;
	protected int TIMEOUT = 30000;// Ĭ����ʮ��
	protected String CHARENCODE = HTTP.UTF_8;
	protected boolean USEGZIP = true;
	protected int HTTP_PORT = 80;
	protected int HTTPS_PORT = 443;
	protected int BUFFER_SIZE = 8192;


	public AnalyseHttpAPI() {
		client = createHttpClient();
		client.setHttpRequestRetryHandler(requestRetryHandler);

	}

	public DefaultHttpClient createHttpClient() {
		// Sets up the http part of the service.
		final SchemeRegistry supportedSchemes = new SchemeRegistry();

		// Register the "http" protocol scheme, it is required
		// by the default operator to look up socket factories.
		final SocketFactory sf = PlainSocketFactory.getSocketFactory();
		supportedSchemes.register(new Scheme("http", sf, HTTP_PORT));
		supportedSchemes.register(new Scheme("https", SSLSocketFactory
				.getSocketFactory(), HTTPS_PORT));

		// Set some client http client parameter defaults.
		final HttpParams httpParams = createHttpParams();

		final ClientConnectionManager ccm = new ThreadSafeClientConnManager(
				httpParams, supportedSchemes);
		return new DefaultHttpClient(ccm, httpParams);
	}

	/**
	 * Create the default HTTP protocol parameters.
	 */
	private final HttpParams createHttpParams() {
		final HttpParams params = new BasicHttpParams();

		// Turn off stale checking. Our connections break all the time anyway,
		// and it's not worth it to pay the penalty of checking every time.
		HttpConnectionParams.setStaleCheckingEnabled(params, false);
		HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);
		HttpConnectionParams.setSoTimeout(params, TIMEOUT);
		HttpConnectionParams.setSocketBufferSize(params, BUFFER_SIZE);
		// �����Ƿ������ض���Ĭ��Ϊtrue��
		// HttpClientParams.setRedirecting(params, false);

		return params;
	}

	// �쳣�Զ��ָ�����, ʹ��HttpRequestRetryHandler�ӿ�ʵ��������쳣�ָ�
	private HttpRequestRetryHandler requestRetryHandler = new HttpRequestRetryHandler() {
		// �Զ���Ļָ�����
		public boolean retryRequest(IOException exception, int executionCount,
				HttpContext context) {
			// ���ûָ����ԣ��ڷ����쳣ʱ���Զ�����3��
			if (executionCount >= 3) {
				// Do not retry if over max retry count
				return false;
			}
			if (exception instanceof NoHttpResponseException) {
				// Retry if the server dropped connection on us
				return true;
			}
			if (exception instanceof SSLHandshakeException) {
				// Do not retry on SSL handshake exception
				return false;
			}
			HttpRequest request = (HttpRequest) context
					.getAttribute(ExecutionContext.HTTP_REQUEST);
			boolean idempotent = (request instanceof HttpEntityEnclosingRequest);
			if (!idempotent) {
				// Retry if the request is considered idempotent
				return true;
			}
			return false;
		}
	};
	// ʹ��ResponseHandler�ӿڴ�����Ӧ��HttpClientʹ��ResponseHandler���Զ��������ӵ��ͷţ�����˶����ӵ��ͷŹ���
	private ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
		// �Զ�����Ӧ����
		public String handleResponse(HttpResponse response)
				throws ClientProtocolException, IOException {
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				Header header = entity.getContentEncoding();
				String charset = EntityUtils.getContentCharSet(entity) == null ? CHARENCODE
						: EntityUtils.getContentCharSet(entity);

				return new String(EntityUtils.toByteArray(entity), charset);
			} else {
				return null;
			}
		}
	};

	


	/***
	 * postͨ�÷���
	 * 
	 * @param list
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public String post(String url, HttpEntity entity,Map<String,String> headers)
			throws ClientProtocolException, IOException {
		HttpPost request = new HttpPost(url);
		if(headers!= null && headers.size()>0){
			for(Entry<String,String> entry:headers.entrySet()){
				request.setHeader(entry.getKey(), entry.getValue());
			}
		}
		request.setEntity(entity);
		String s = client.execute(request, responseHandler);
		return s;
	}
	public String post(String url, List<NameValuePair> olist,Map<String,String> headers)
			throws ClientProtocolException, IOException {
		return post(url,new UrlEncodedFormEntity(olist,CHARENCODE),headers);
	}
	
	public InputStream postWithStream(String url, HttpEntity entity) throws ClientProtocolException, IOException{
		return  getUngzippedStream(postWithHttpEntity(url, entity));
	}
	public HttpEntity postWithHttpEntity(String url, HttpEntity entity) throws ClientProtocolException, IOException{
		HttpPost request = new HttpPost(url);
		// ����ͷ������
		request.setEntity(entity);
		HttpResponse response =  client.execute(request);
		return response.getEntity();
	}
	public BasicNameValuePair generateGetParameter(String name, String value) {
		return new BasicNameValuePair(name, value);
	}
	 /**
     * Gets the input stream from a response entity. If the entity is gzipped then this will get a
     * stream over the uncompressed data.
     *
     * @param entity the entity whose content should be read
     * @return the input stream to read from
     * @throws IOException
     */
    public InputStream getUngzippedStream(HttpEntity entity) throws IOException {
        InputStream responseStream = entity.getContent();
        if (responseStream == null) {
            return responseStream;
        }
        Header header = entity.getContentEncoding();
        if (header == null) {
            return responseStream;
        }
        String contentEncoding = header.getValue();
        if (contentEncoding == null) {
            return responseStream;
        }
        if (contentEncoding.contains("gzip")) {
            responseStream = new GZIPInputStream(responseStream);
        }
        return responseStream;
    }
}
